// Copyright (c) 2003-2019 by Kithara Software GmbH. All rights reserved.

//##############################################################################
//
// File:             _KitharaSmp.cs
//
// Description:      Helper class with convenience functions for C# samples
//
// Creator:          a.lun 2003-03-10
//
//##############################################################################

   /*=====================================================================*\
   |                    *** DISCLAIMER OF WARRANTY ***                     |
   |                                                                       |
   |       THIS  CODE AND INFORMATION IS PROVIDED "AS IS"  WITHOUT         |
   |       A  WARRANTY OF  ANY KIND, EITHER  EXPRESSED OR  IMPLIED,        |
   |       INCLUDING  BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF         |
   |       MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.        |
   \*=====================================================================*/

//##############################################################################
//
// Purpose:
// This class is a helper class for all of our sample programs. It gathers some
// commonly used input and output functions, which are compatible to the other
// programming languages and environments supported.
//
// We are extending the class Kithara here so we can use all functions and
// constants right as we would do in other languages. This allows you to call
// Kithara functions without prepending 'Kithara.' everywhere. In your own
// programs you have two choices: either inheriting from the class Kithara
// or writing 'Kithara.' before every usage of a function or constant.
//
// See file Kithara.cs in sub-directory dev\ for details.
//
//##############################################################################


//------------------------------------------------------------------------------
// _KitharaSmp
//------------------------------------------------------------------------------

using System;
using System.Text;
using System.Globalization;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;


public class _KitharaSmp : Kithara {
  //------ mikrosecond definition ------
  public const int us = 10;
  //------ millisecond definition ------
  public const int ms = us * 1000;
  //------ second definition ------
  public const int s = ms * 1000;
  //------ error mask defintion ------
  public const int error_mask = 0x3fff0000;

  public static void outputTxt(string txt, ConsoleColor color) {
    outputTxt(txt, true, color);
  }
  public static void outputTxt(string txt, bool line, ConsoleColor color) {
    ConsoleColor c = Console.ForegroundColor;
    Console.ForegroundColor = color;
    outputTxt(txt, line);
    Console.ForegroundColor = c;
  }
  public static void outputTxt(char[] chars) {
    outputTxt(chars, true);
  }
  public static void outputTxt(byte[] chars) {
    outputTxt(chars, true);
  }
  public static unsafe void outputTxt(sbyte* chars) {
    outputTxt(new String(chars));
  }
  public static unsafe void outputTxt(char* chars) {
    outputTxt((sbyte*)chars);
  }
  public static void outputTxt(string txt) {
    outputTxt(txt, true);
  }
  public static void outputBool(int value, string preTxt, string postTxt)
  {
    outputBool(value, preTxt, postTxt, true);
  }
  public static void outputBool(int value, string preTxt)
  {
    outputBool(value, preTxt, "", true);
  }
  public static void outputBool(int value)
  {
    outputBool(value, "", "", true);
  }
  public static void outputFloat(double value, string preTxt, string postTxt) {
    outputFloat(value, preTxt, postTxt, true);
  }
  public static void outputFloat(double value, string preTxt) {
    outputFloat(value, preTxt, "", true);
  }
  public static void outputFloat(double value) {
    outputFloat(value, "", "", true);
  }
  public static void outputDec(int value, string preTxt, string postTxt) {
    outputDec(value, preTxt, postTxt, true);
  }
  public static void outputDec(int value, string preTxt) {
    outputDec(value, preTxt, "", true);
  }
  public static void outputDec(int value) {
    outputDec(value, "", "", true);
  }
  public static void outputHex04(int value, string preTxt, string postTxt) {
    outputHex04(value, preTxt, postTxt, true);
  }
  public static unsafe void outputErr(int error, string funcName) {
    outputErr(error, funcName, "");
  }
  public static string inputTxt(string preTxt) {
    return inputTxt(preTxt, "");
  }
  public static int inputDec(string preTxt) {
    return inputDec(preTxt, "0");
  }
  public static int inputHex(string preTxt) {
    return inputHex(preTxt, "0");
  }

  public static string charsToString(char[] chars) {
    StringBuilder sb = new StringBuilder(chars.Length);
    //to filter '\0' chars
    int i = 0;
    while (chars[i] != '\0') {
      sb.Append(chars[i]);
      ++i;
    }
    return sb.ToString();
  }
  public static string bytesToString(byte[] bytes) {
    return Encoding.ASCII.GetString(bytes);
  }
  //------ outputBytes ------
  public static void outputTxt(byte[] bytes, bool line) {
    outputTxt(bytesToString(bytes), line);
  }
  //------ outputChars ------
  public static void outputTxt(char[] chars, bool line) {
    outputTxt(charsToString(chars),line);
  }
  //------ outputTxt ------
  public static void outputTxt(string txt, bool line) {
    if (line)
      Console.WriteLine(txt);
    else
      Console.Write(txt);
  }

  //------ outputBool ------
  public static void outputBool(int value, string preTxt, string postTxt, bool line) {
    string txt = preTxt + (value == 0 ? "false" : "true") + postTxt;
    outputTxt(txt, line);
  }

 //------ outputFloat ------
  public static void outputFloat(double value, string preTxt, string postTxt, bool line) {
    string txt = string.Format("{0}{1:F2}{2}", preTxt, value, postTxt);
    outputTxt(txt, line);
  }

  //------ outputDec ------
  public static void outputDec(int value, string preTxt, string postTxt, bool line) {
    string txt = preTxt + value + postTxt;
    outputTxt(txt, line);
  }

  //------ outputHex02 ------
  public static void outputHex02(int value, string preTxt, string postTxt, bool line)
  {
    string pTxt = string.Format("{0}{1:x2}{2}", preTxt, value, postTxt);
    outputTxt(pTxt, line);
  }

  //------ outputHex04 ------
  public static void outputHex04(int value, string preTxt, string postTxt, bool line) {
    string pTxt = string.Format("{0}{1:x4}{2}", preTxt, value, postTxt);
    outputTxt(pTxt, line);
  }

  //------ outputHex08 ------
  public static void outputHex08(int value, string preTxt, string postTxt, bool line) {
    string pTxt = string.Format("{0}{1:x8}{2}", preTxt, value, postTxt);
    outputTxt(pTxt, line);
  }

  //------ outputHex16 ------
  public static void outputHex16(Int64 value, string preTxt, string postTxt, bool line) {
    string pTxt = string.Format("{0}{1:x16}{2}", preTxt, value, postTxt);
    outputTxt(pTxt, line);
  }

  //------ outputErr ------
  public static unsafe void outputErr(int error, string funcName, string comment)
  {
    if (error == KS_OK)
      return;

    byte* buf;
    KS_getErrorString(error, &buf, KSLNG_DEFAULT);
    string msg = new string((sbyte*)buf);

    ConsoleColor prev = Console.ForegroundColor;
    Console.ForegroundColor = ConsoleColor.Red;
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("{0:X}", error);
    outputTxt("ERROR (" + sb + "=" + msg + ") -\n" + funcName + ": " + comment, true);
    Console.ForegroundColor = prev;
    if (KS_getErrorDescription(error, funcName, &buf, KSLNG_DEFAULT) == KS_OK) {
      string descr = new string((sbyte*)buf);
      outputTxt(descr);
    }
  }

  //------ outputStruct ------
  public static void outputStruct(object structure, Type structType) {
    System.Text.StringBuilder sb = new System.Text.StringBuilder(structType.ToString() + " \n\r");
    System.Reflection.FieldInfo[] fields = structType.GetFields();

    foreach (System.Reflection.FieldInfo f in fields) {
      sb.Append(f.Name + " = ");

      if (f.FieldType.IsArray && f.FieldType.Name == typeof(char[]).Name)

        Array.ForEach<char>((char[])f.GetValue(structure), delegate(char a) { if (a != '\0') sb.Append(a); });

      else if (f.FieldType.IsArray && f.FieldType.Name == typeof(byte[]).Name)

        Array.ForEach<byte>((byte[])f.GetValue(structure), delegate(byte a) { if (a != 0) sb.Append((char)a); });

      else
        sb.Append(f.GetValue(structure));
      sb.AppendLine(" ");
    }

    outputTxt(sb.ToString());
  }

  public static unsafe void outputStructPointer(void* pStruct, Type structType) {
    outputStruct(
      System.Runtime.InteropServices.Marshal.PtrToStructure(new IntPtr(pStruct), structType),
      structType);
  }

  //------ inputTxt ------
  public static string inputTxt(string preTxt, string defaultTxt) {
    outputTxt(preTxt, false);
    if (defaultTxt != "")
      outputTxt("[" + defaultTxt + "] ", false);
    string line = Console.ReadLine();
    if (line == "")
      line = defaultTxt;
    return line;
  }

  //------ inputDec ------
  public static int inputDec(string preTxt, string defaultDec) {
    try {
      return System.Convert.ToInt32(inputTxt(preTxt, defaultDec));
    }
    catch (System.Exception) {
      return -1;
    }
  }

  //------ inputDec ------
  public static int inputDec(string preTxt, int defaultDec) {
    return inputDec(preTxt, string.Format("{0}", defaultDec));
  }

  //------ inputHex ------
  public static int inputHex(string preTxt, string defaultHex) {
    string txt = inputTxt(preTxt, defaultHex);
    return int.Parse(txt, NumberStyles.HexNumber, new NumberFormatInfo());
  }

  //------ inputHex ------
  public static int inputHex(string preTxt, int defaultHex) {
    return inputHex(preTxt, string.Format("{0:X}", defaultHex));
  }

  //------ myKbhit ------
  public static bool myKbhit() {
    return System.Console.KeyAvailable;
  }

  //------ myGetch ------
  public static char myGetch() {
    return System.Console.ReadKey(true).KeyChar;
  }

  //------ waitTime ------
  public static void waitTime(int time) {
    try {
      Thread.Sleep(time / 10000);
    }
    catch (System.ArgumentOutOfRangeException) {
    }
  }
  //------ switchColor ------
  public static void switchColor(ConsoleColor color) {
    _stdColor_ = Console.ForegroundColor;
    Console.ForegroundColor = color;
  }
  //------ switchStdColor ------
  public static void switchStdColor() {
    Console.ForegroundColor = _stdColor_;
  }
  //------ kserrCode ------
  public static int kserrCode(int error) {
    return error & error_mask;
  }

  private static ConsoleColor _stdColor_;
}
